//
//  XSPhotosManager.m
//  AudioVideo
//
//  Created by xueshan1 on 2019/9/11.
//  Copyright © 2019 xueshan1. All rights reserved.
//

#import "XSPhotosManager.h"
#import "XSNavigationController.h"

static BOOL _sortAscending = NO;

@implementation XSPhotosManager

//存储到相册
+ (void)saveToPhotoLibrary:(NSURL *)outputURL completion:(void(^)(NSError *error))completion{
    __block PHObjectPlaceholder *placeholder;
    if (UIVideoAtPathIsCompatibleWithSavedPhotosAlbum(outputURL.path)) {
        MBProgressHUD *hud =[MBProgressHUD showHUDAddedTo:KeyWindow animated:YES];
        hud.label.text = @"保存到相册...";
        NSError *error;
        [[PHPhotoLibrary sharedPhotoLibrary] performChangesAndWait:^{
            PHAssetChangeRequest* createAssetRequest = [PHAssetChangeRequest creationRequestForAssetFromVideoAtFileURL:outputURL];
            placeholder = [createAssetRequest placeholderForCreatedAsset];
        } error:&error];
        if (error) {
            NSLog(@"error:%@",error);
            hud.label.text = @"保存失败";
            dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
                [hud hideAnimated:YES];
                if (completion) completion(error);
            });
        }
        else{
            hud.label.text = @"保存成功";
            dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
                [hud hideAnimated:YES];
                if (completion) completion(nil);
            });
        }
        
    }else {
        if (completion) completion([NSError errorWithDomain:NSStringFromClass(self.class) code:0 userInfo:@{@"error":@"视频保存相册失败，请设置软件读取相册权限"}]);
        NSLog(@"视频保存相册失败，请设置软件读取相册权限");
        MBProgressHUD *hud =[MBProgressHUD showHUDAddedTo:KeyWindow animated:YES];
        hud.label.text = @"视频保存相册失败，请设置软件读取相册权限";
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            [hud hideAnimated:YES];
        });
    }
    
}
#pragma mark - 保存图片到系统相册
//会新建当前 app name 的相册,
+ (void)saveImageToAblum:(UIImage *)image completion:(void (^)(BOOL success, PHAsset *asset))completion
{
    PHAuthorizationStatus status = [PHPhotoLibrary authorizationStatus];
    if (status == PHAuthorizationStatusDenied) {
        if (completion) completion(NO, nil);
    } else if (status == PHAuthorizationStatusRestricted) {
        if (completion) completion(NO, nil);
    } else {
        __block PHObjectPlaceholder *placeholderAsset=nil;
        [[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
            PHAssetChangeRequest *newAssetRequest = [PHAssetChangeRequest creationRequestForAssetFromImage:image];
            placeholderAsset = newAssetRequest.placeholderForCreatedAsset;
        } completionHandler:^(BOOL success, NSError *  error) {
            if (!success) {
                if (completion) completion(NO, nil);
                return;
            }
            PHAsset *asset = [self getAssetFromlocalIdentifier:placeholderAsset.localIdentifier];
            PHAssetCollection *desCollection = [self getDestinationCollection];
            if (!desCollection) completion(NO, nil);
            
            [[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
                [[PHAssetCollectionChangeRequest changeRequestForAssetCollection:desCollection] addAssets:@[asset]];
            } completionHandler:^(BOOL success, NSError *  error) {
                if (completion) completion(success, asset);
                //
                dispatch_async(dispatch_get_main_queue(), ^{
                    MBProgressHUD *hud =[MBProgressHUD showHUDAddedTo:KeyWindow animated:YES];
                    if (success) {
                        hud.label.text = @"保存成功";
                    }else{
                        hud.label.text = @"保存失败";
                        NSLog(@"%@",error);
                    }
                    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
                        [hud hideAnimated:YES];
                    });
                });
                //
            }];
        }];
    }
}
#pragma mark - 保存视频到系统相册
+ (void)saveVideoToAblum:(NSURL *)url completion:(void (^)(BOOL success, PHAsset *asset))completion
{
    PHAuthorizationStatus status = [PHPhotoLibrary authorizationStatus];
    if (status == PHAuthorizationStatusDenied) {
        if (completion) completion(NO, nil);
    } else if (status == PHAuthorizationStatusRestricted) {
        if (completion) completion(NO, nil);
    } else {
        __block PHObjectPlaceholder *placeholderAsset=nil;
        [[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
            PHAssetChangeRequest *newAssetRequest = [PHAssetChangeRequest creationRequestForAssetFromVideoAtFileURL:url];
            placeholderAsset = newAssetRequest.placeholderForCreatedAsset;
        } completionHandler:^(BOOL success, NSError *  error) {
            if (!success) {
                if (completion) completion(NO, nil);
                return;
            }
            PHAsset *asset = [self getAssetFromlocalIdentifier:placeholderAsset.localIdentifier];
            PHAssetCollection *desCollection = [self getDestinationCollection];
            if (!desCollection) completion(NO, nil);
            
            [[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
                [[PHAssetCollectionChangeRequest changeRequestForAssetCollection:desCollection] addAssets:@[asset]];
            } completionHandler:^(BOOL success, NSError *  error) {
                //
                dispatch_async(dispatch_get_main_queue(), ^{
                    MBProgressHUD *hud =[MBProgressHUD showHUDAddedTo:KeyWindow animated:YES];
                    if (success) {
                        hud.label.text = @"保存成功";
                    }else{
                        hud.label.text = @"保存失败";
                        NSLog(@"%@",error);
                    }
                    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
                        [hud hideAnimated:YES];
                        if (completion) completion(success, asset);
                    });
                });
                //
            }];
        }];
    }
}
+ (PHAsset *)getAssetFromlocalIdentifier:(NSString *)localIdentifier{
    if(localIdentifier == nil){
        NSLog(@"Cannot get asset from localID because it is nil");
        return nil;
    }
    PHFetchResult *result = [PHAsset fetchAssetsWithLocalIdentifiers:@[localIdentifier] options:nil];
    if(result.count){
        return result[0];
    }
    return nil;
}
//获取自定义相册
+ (PHAssetCollection *)getDestinationCollection
{
    //找是否已经创建自定义相册
    PHFetchResult<PHAssetCollection *> *collectionResult = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeAlbum subtype:PHAssetCollectionSubtypeAlbumRegular options:nil];
    for (PHAssetCollection *collection in collectionResult) {
        if ([collection.localizedTitle isEqualToString:kAPPName]) {
            return collection;
        }
    }
    //新建自定义相册
    __block NSString *collectionId = nil;
    NSError *error = nil;
    [[PHPhotoLibrary sharedPhotoLibrary] performChangesAndWait:^{
        collectionId = [PHAssetCollectionChangeRequest creationRequestForAssetCollectionWithTitle:kAPPName].placeholderForCreatedAssetCollection.localIdentifier;
    } error:&error];
    if (error) {
        NSLog(@"创建相册：%@失败", kAPPName);
        return nil;
    }
    return [PHAssetCollection fetchAssetCollectionsWithLocalIdentifiers:@[collectionId] options:nil].lastObject;
}




+ (instancetype)shareInstance{
    static XSPhotosManager *manager = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        manager = [XSPhotosManager new];
    });
    return manager;
}
 
+ (void)showImagePickerController:(UIViewController *)targeVC selectVideo:(BOOL)selectVideo complete:(void(^)(NSArray<XSPhotoModel *>  *array))complete
{
    [self showImagePickerController:targeVC selectVideo:selectVideo maxCount:1 complete:complete];
}

+ (void)showImagePickerController:(UIViewController *)targeVC selectVideo:(BOOL)selectVideo maxCount:(NSInteger)maxCount complete:(void(^)(NSArray<XSPhotoModel *>  *array))complete{
    XSAlbumListViewController *albumListVC = [XSAlbumListViewController new];
    XSNavigationController *nav = [[XSNavigationController alloc]initWithRootViewController:albumListVC];
    XSThumbnailViewController *thumbVC = [XSThumbnailViewController new];
    nav.modalPresentationStyle = UIModalPresentationFullScreen;
    albumListVC.selectVideo = selectVideo;
    thumbVC.selectVideo = selectVideo;
    thumbVC.canPanSelectItem = !selectVideo;
    thumbVC.maxSelectCount = maxCount?maxCount:1;
    
    [XSPhotosManager shareInstance].selectedPhtotosBlock = ^(NSArray<XSPhotoModel *> *selectedPhotos) {
        if (selectedPhotos.count == 0) {
            NSLog(@"unselect photo");
        }
        if (complete) {
            complete(selectedPhotos);
        }
    };
    
    [nav pushViewController:thumbVC animated:NO];
    [targeVC presentViewController:nav animated:YES completion:nil];
    
}

+ (void)setSortAscending:(BOOL)ascending{
    _sortAscending = ascending;
}

+ (BOOL)sortAscending{
    return _sortAscending;
}

#pragma mark - 获取 "相机胶卷" 相册
+ (void)getCameraRollAlbumListAllowSelectVideo:(BOOL)allowSelectVideo allowSelectImage:(BOOL)allowSelectImage complete:(void (^)(XSAlbumListModel * albumModel))complete
{
    if (complete) {
        complete([self getCameraRollAlbumList:allowSelectVideo allowSelectImage:allowSelectImage]);
    }
}
#pragma mark - 获取 所有相册 列表
+ (void)getAlbumList:(BOOL)allowSelectVideo allowSelectImage:(BOOL)allowSelectImage complete:(void(^)(NSArray<XSAlbumListModel *>* albumList))complete{
    if (!allowSelectImage && !allowSelectVideo) {
        if (complete) complete(nil);
        return;
    }
    PHFetchOptions *option = [[PHFetchOptions alloc] init];
    if (!allowSelectVideo) option.predicate = [NSPredicate predicateWithFormat:@"mediaType == %ld", PHAssetMediaTypeImage];
    if (!allowSelectImage) option.predicate = [NSPredicate predicateWithFormat:@"mediaType == %ld",PHAssetMediaTypeVideo];
    if (!self.sortAscending) option.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"creationDate" ascending:self.sortAscending]];
    
    //获取所有智能相册
    PHFetchResult *smartAlbums = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeSmartAlbum subtype:PHAssetCollectionSubtypeAlbumRegular options:nil];
    PHFetchResult *streamAlbums = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeAlbum subtype:PHAssetCollectionSubtypeAlbumMyPhotoStream options:nil];
    PHFetchResult *userAlbums = [PHCollectionList fetchTopLevelUserCollectionsWithOptions:nil];
    PHFetchResult *syncedAlbums = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeAlbum subtype:PHAssetCollectionSubtypeAlbumSyncedAlbum options:nil];
    PHFetchResult *sharedAlbums = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeAlbum subtype:PHAssetCollectionSubtypeAlbumCloudShared options:nil];
    NSArray *arrAllAlbums = @[smartAlbums, streamAlbums, userAlbums, syncedAlbums, sharedAlbums];
    /**
     PHAssetCollectionSubtypeAlbumRegular         = 2,///
     PHAssetCollectionSubtypeAlbumSyncedEvent     = 3,////
     PHAssetCollectionSubtypeAlbumSyncedFaces     = 4,////面孔
     PHAssetCollectionSubtypeAlbumSyncedAlbum     = 5,////
     PHAssetCollectionSubtypeAlbumImported        = 6,////
     
     // PHAssetCollectionTypeAlbum shared subtypes
     PHAssetCollectionSubtypeAlbumMyPhotoStream   = 100,///
     PHAssetCollectionSubtypeAlbumCloudShared     = 101,///
     
     // PHAssetCollectionTypeSmartAlbum subtypes        //// collection.localizedTitle
     PHAssetCollectionSubtypeSmartAlbumGeneric    = 200,///
     PHAssetCollectionSubtypeSmartAlbumPanoramas  = 201,///全景照片
     PHAssetCollectionSubtypeSmartAlbumVideos     = 202,///视频
     PHAssetCollectionSubtypeSmartAlbumFavorites  = 203,///个人收藏
     PHAssetCollectionSubtypeSmartAlbumTimelapses = 204,///延时摄影
     PHAssetCollectionSubtypeSmartAlbumAllHidden  = 205,/// 已隐藏
     PHAssetCollectionSubtypeSmartAlbumRecentlyAdded = 206,///最近添加
     PHAssetCollectionSubtypeSmartAlbumBursts     = 207,///连拍快照
     PHAssetCollectionSubtypeSmartAlbumSlomoVideos = 208,///慢动作
     PHAssetCollectionSubtypeSmartAlbumUserLibrary = 209,///所有照片
     PHAssetCollectionSubtypeSmartAlbumSelfPortraits NS_AVAILABLE_IOS(9_0) = 210,///自拍
     PHAssetCollectionSubtypeSmartAlbumScreenshots NS_AVAILABLE_IOS(9_0) = 211,///屏幕快照
     PHAssetCollectionSubtypeSmartAlbumDepthEffect PHOTOS_AVAILABLE_IOS_TVOS(10_2, 10_1) = 212,///人像
     PHAssetCollectionSubtypeSmartAlbumLivePhotos PHOTOS_AVAILABLE_IOS_TVOS(10_3, 10_2) = 213,//livephotos
     PHAssetCollectionSubtypeSmartAlbumAnimated = 214,///动图
     = 1000000201///最近删除知道值为（1000000201）但没找到对应的TypedefName
     // Used for fetching, if you don't care about the exact subtype
     PHAssetCollectionSubtypeAny = NSIntegerMax /////所有类型
     */
    
    NSMutableArray<XSAlbumListModel *> *arrAlbum = [NSMutableArray array];
    for (PHFetchResult<PHAssetCollection *> *album in arrAllAlbums) {
        //枚举每一个collection
        [album enumerateObjectsUsingBlock:^(PHAssetCollection * _Nonnull collection, NSUInteger idx, BOOL *stop) {
            //过滤PHCollectionList对象
            if (![collection isKindOfClass:PHAssetCollection.class]) return;
            //过滤最近删除和已隐藏
            if (collection.assetCollectionSubtype > 215 ||
                collection.assetCollectionSubtype == PHAssetCollectionSubtypeSmartAlbumAllHidden) return;
            //获取相册内asset result
            PHFetchResult<PHAsset *> *result = [PHAsset fetchAssetsInAssetCollection:collection options:option];
            if (!result.count) return;
            
            NSString *title = [self getCollectionTitle:collection];
            XSAlbumListModel *model = [self getAlbumListModelWithTitle:title fetchResult:result allowSelectVideo:allowSelectVideo allowSelectImage:allowSelectImage];

            if (collection.assetCollectionSubtype == PHAssetCollectionSubtypeSmartAlbumUserLibrary) {
                //所有照片
                model.isCameraRoll = YES;
                [arrAlbum insertObject:model atIndex:0];
            } else {
                [arrAlbum addObject:model];
            }
        }];
    }
    
    if (complete) complete(arrAlbum);
    
}

#pragma mark - album

/**
 获取 "相机胶卷" 相册

 @param allowSelectVideo 选视频
 @param allowSelectImage 选图片 
 @return 相册model
 */
+ (XSAlbumListModel *)getCameraRollAlbumList:(BOOL)allowSelectVideo allowSelectImage:(BOOL)allowSelectImage
{
    PHFetchOptions *option = [[PHFetchOptions alloc] init];
    if (!allowSelectVideo) option.predicate = [NSPredicate predicateWithFormat:@"mediaType == %ld", PHAssetMediaTypeImage];
    if (!allowSelectImage) option.predicate = [NSPredicate predicateWithFormat:@"mediaType == %ld",PHAssetMediaTypeVideo];
    if (!self.sortAscending) option.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"creationDate" ascending:self.sortAscending]]; //排序
    
    PHFetchResult<PHAssetCollection *> *smartAlbums = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeSmartAlbum subtype:PHAssetCollectionSubtypeAlbumRegular options:nil];
    
    __block XSAlbumListModel *m;
    [smartAlbums enumerateObjectsUsingBlock:^(PHAssetCollection *  _Nonnull collection, NSUInteger idx, BOOL * _Nonnull stop) {
        //获取相册内asset result
        if (collection.assetCollectionSubtype == 209) {
            PHFetchResult<PHAsset *> *result = [PHAsset fetchAssetsInAssetCollection:collection options:option];
            m = [self getAlbumListModelWithTitle:[self getCollectionTitle:collection] fetchResult:result allowSelectVideo:allowSelectVideo allowSelectImage:allowSelectImage];
            m.isCameraRoll = YES;
        }
    }];
    return m;
}


#pragma mark - model
//获取相册model
+ (XSAlbumListModel *)getAlbumListModelWithTitle:(NSString *)title fetchResult:(PHFetchResult <PHAsset *>*)fetchResult allowSelectVideo:(BOOL)allowSelectVideo allowSelectImage:(BOOL)allowSelectImage
{
    XSAlbumListModel *albumModel = [[XSAlbumListModel alloc]init];
    albumModel.title = title;
    albumModel.count = fetchResult.count;
    albumModel.fetchResult = fetchResult;
    if (self.sortAscending) {
        albumModel.headImageAsset = fetchResult.lastObject;
    } else {
        albumModel.headImageAsset = fetchResult.firstObject;
    }
    
    albumModel.models = [self getPhotoModelsWithFetchResult:fetchResult allowSelectVideo:allowSelectVideo allowSelectImage:allowSelectImage allowSelectGif:allowSelectImage allowSelectLivePhoto:allowSelectImage limitCount:NSIntegerMax];
    
    return albumModel;
}

//获取某个相册内的limit个数的资源
+ (NSArray<XSPhotoModel *>*)getPhotoModelsWithFetchResult:(PHFetchResult<PHAsset *>*)fetchResult allowSelectVideo:(BOOL)allowSelectVideo allowSelectImage:(BOOL)allowSelectImage allowSelectGif:(BOOL)allowSelectGif allowSelectLivePhoto:(BOOL)allowSelectLivePhoto limitCount:(NSInteger)limit{
    
    NSMutableArray <XSPhotoModel *> *array = [NSMutableArray array];
    __block NSInteger count = 1;
    [fetchResult enumerateObjectsUsingBlock:^(PHAsset * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
       
        XSAssetMediaType type = [self transformAssetType:obj];
        
        if (type == XSAssetMediaTypeImage && !allowSelectImage) return;
        if (type == XSAssetMediaTypeGif && !allowSelectImage) return;
        if (type == XSAssetMediaTypeLivePhoto && !allowSelectImage) return;
        if (type == XSAssetMediaTypeVideo && !allowSelectVideo) return;
        
        if (count == limit) {
            *stop = YES;
        }
        
        NSString *duration = [self getDuration:obj];
        XSPhotoModel *photoModel = [XSPhotoModel modelWithAsset:obj type:type duration:duration];
        [array addObject:photoModel];

    }];
    
    return array;
}

//系统mediatype 转换为 自定义type
+ (XSAssetMediaType)transformAssetType:(PHAsset *)asset
{
    switch (asset.mediaType) {
        case PHAssetMediaTypeAudio:
            return XSAssetMediaTypeAudio;
        case PHAssetMediaTypeVideo:
            return XSAssetMediaTypeVideo;
        case PHAssetMediaTypeImage:
            if ([[asset valueForKey:@"filename"] hasSuffix:@"GIF"]){
                return XSAssetMediaTypeGif;
            }
            if (asset.mediaSubtypes == PHAssetMediaSubtypePhotoLive || asset.mediaSubtypes == 10){
                return XSAssetMediaTypeLivePhoto;
            }
            
            return XSAssetMediaTypeImage;
        default:
            return XSAssetMediaTypeUnknown;
    }
}

+ (NSString *)getCollectionTitle:(PHAssetCollection *)collection{
    if (collection.assetCollectionType == PHAssetCollectionTypeAlbum) {
        //用户相册
        return collection.localizedTitle;
    }
  
    return collection.localizedTitle;
}

+ (NSString *)getDuration:(PHAsset *)asset
{
    if (asset.mediaType != PHAssetMediaTypeVideo) return nil;
    
    NSInteger duration = (NSInteger)round(asset.duration);
    
    if (duration < 60) {
        return [NSString stringWithFormat:@"00:%02ld", duration];
    } else if (duration < 3600) {
        NSInteger m = duration / 60;
        NSInteger s = duration % 60;
        return [NSString stringWithFormat:@"%02ld:%02ld", m, s];
    } else {
        NSInteger h = duration / 3600;
        NSInteger m = (duration % 3600) / 60;
        NSInteger s = duration % 60;
        return [NSString stringWithFormat:@"%02ld:%02ld:%02ld", h, m, s];
    }
}

#pragma mark - 获取asset对应的图片
+ (void)requestOriginalImageForAsset:(XSPhotoModel *)photoModel progressHandler:(void (^ )(double progress, NSError *error, BOOL *stop, NSDictionary *info))progressHandler completion:(void (^)(UIImage *image, NSDictionary *dic))completion
{
    CGSize size = CGSizeMake(kWidth, kWidth * photoModel.asset.pixelHeight/photoModel.asset.pixelWidth);
    [self requestImageForAsset:photoModel.asset size:size resizeMode:PHImageRequestOptionsResizeModeNone progressHandler:progressHandler completion:completion];
}

+ (PHImageRequestID)requestImageWithModel:(XSPhotoModel *)photoModel completion:(void (^)(UIImage *image, NSDictionary *info))completion
{
    if (photoModel == nil) return 0;
    CGSize size = CGSizeMake(kWidth, kWidth * photoModel.asset.pixelHeight/photoModel.asset.pixelWidth);
    return [self requestImageForAsset:photoModel.asset size:size resizeMode:PHImageRequestOptionsResizeModeFast progressHandler:nil completion:completion];
}
+ (PHImageRequestID)requestImageForAsset:(PHAsset *)asset size:(CGSize)size progressHandler:(void (^)(double progress, NSError *error, BOOL *stop, NSDictionary *info))progressHandler completion:(void (^)(UIImage *image, NSDictionary *info))completion
{
    return [self requestImageForAsset:asset size:size resizeMode:PHImageRequestOptionsResizeModeFast progressHandler:progressHandler completion:completion];
}
//https://www.jianshu.com/p/f05a0675df24
+ (PHImageRequestID)requestImageForAsset:(PHAsset *)asset size:(CGSize)size resizeMode:(PHImageRequestOptionsResizeMode)resizeMode progressHandler:(void (^ )(double progress, NSError *error, BOOL *stop, NSDictionary *info))progressHandler completion:(void (^)(UIImage *, NSDictionary *))completion
{
    PHImageRequestOptions *option = [[PHImageRequestOptions alloc] init];
   
    option.resizeMode = resizeMode;//控制照片尺寸
    /*
     PHImageRequestOptionsResizeModeNone = 0,(原图)不压缩
     PHImageRequestOptionsResizeModeFast,高效率请求,但是返回的图片尺寸可能和要求的尺寸不同
     PHImageRequestOptionsResizeModeExact,按照精准尺寸返回
     */
    
    // 同步获得图片, 只会返回1张图片,PS: 若options.synchronous = YES,则不论options.deliveryMode如何设置,系统会选择PHImageRequestOptionsDeliveryModeHighQualityFormat(高质量图片)
    option.synchronous = YES;
    option.deliveryMode = PHImageRequestOptionsDeliveryModeHighQualityFormat;//控制照片质量
    /*
     PHImageRequestOptionsDeliveryModeOpportunistic = 0,图片获取速度和质量的平衡
     PHImageRequestOptionsDeliveryModeHighQualityFormat = 1,高质量图片,
     PHImageRequestOptionsDeliveryModeFastFormat = 2 快速得到图片的情况下保证质量 ; 这个属性只有在 synchronous 为 true 时有效
     */
    option.networkAccessAllowed = NO;//是否联网获取iCloud的图片
    
    option.progressHandler = progressHandler;
    
    /*
     info字典提供请求状态信息:
     PHImageResultIsInCloudKey：图像是否必须从iCloud请求
     PHImageResultIsDegradedKey：当前UIImage是否是低质量的，这个可以实现给用户先显示一个预览图
     PHImageResultRequestIDKey和PHImageCancelledKey：请求ID以及请求是否已经被取消
     PHImageErrorKey：如果没有图像，字典内的错误信息
     */
    
    return [[PHCachingImageManager defaultManager] requestImageForAsset:asset targetSize:size contentMode:PHImageContentModeAspectFill options:option resultHandler:^(UIImage *  image, NSDictionary *  info) {
        BOOL downloadFinined = ![[info objectForKey:PHImageCancelledKey] boolValue] && ![info objectForKey:PHImageErrorKey];
        //不要该判断，即如果该图片在iCloud上时候，会先显示一张模糊的预览图，待加载完毕后会显示高清图
        // && ![[info objectForKey:PHImageResultIsDegradedKey] boolValue]
        if (downloadFinined && completion) {
            completion(image, info);
        }
    }];
}

+ (void)getPhotosBytesWithArray:(NSArray<XSPhotoModel *> *)photos completion:(void (^)(NSString *photosBytes))completion
{
    __block NSInteger dataLength = 0;
    __block NSInteger count = photos.count;
    
    __weak typeof(self) weakSelf = self;
    for (int i = 0; i < photos.count; i++) {
        XSPhotoModel *model = photos[i];
        [[PHCachingImageManager defaultManager] requestImageDataForAsset:model.asset options:nil resultHandler:^(NSData *  imageData, NSString *  dataUTI, UIImageOrientation orientation, NSDictionary *  info) {
            __strong typeof(weakSelf) strongSelf = weakSelf;
            dataLength += imageData.length;
            count--;
            if (count <= 0) {
                if (completion) {
                    completion([strongSelf transformDataLength:dataLength]);
                }
            }
        }];
    }
}

+ (void)getPhotosBytesWithModel:(XSPhotoModel*)model completion:(void (^)(NSString *photosBytes))completion{
    __block NSInteger dataLength = 0;
    if (model) {
        [[PHCachingImageManager defaultManager] requestImageDataForAsset:model.asset options:nil resultHandler:^(NSData *  imageData, NSString *  dataUTI, UIImageOrientation orientation, NSDictionary *  info) {
             dataLength = imageData.length;
 
            if (completion) {
                completion([self transformDataLength:dataLength]);
            }
        
        }];
    }
    
}

+ (NSString *)transformDataLength:(NSInteger)dataLength {
    NSString *bytes = @"";
    if (dataLength >= 0.1 * (1024 * 1024)) {
        bytes = [NSString stringWithFormat:@"%.1fM",dataLength/1024/1024.0];
    } else if (dataLength >= 1024) {
        bytes = [NSString stringWithFormat:@"%.0fK",dataLength/1024.0];
    } else {
        bytes = [NSString stringWithFormat:@"%zdB",dataLength];
    }
    return bytes;
}

#pragma mark - Video
+ (void)requestVideoForAsset:(PHAsset *)asset progressHandler:(void (^)(double progress, NSError *error, BOOL *stop, NSDictionary *info))progressHandler completion:(void (^)(AVPlayerItem *item, NSDictionary *info))completion
{
    PHVideoRequestOptions *option = [[PHVideoRequestOptions alloc] init];
    option.networkAccessAllowed = YES;
    option.version = PHVideoRequestOptionsVersionOriginal;
    option.deliveryMode = PHVideoRequestOptionsDeliveryModeAutomatic;
    option.progressHandler = ^(double progress, NSError *error, BOOL *stop, NSDictionary *info) {
        dispatch_async(dispatch_get_main_queue(), ^{
            if (progressHandler) {
                progressHandler(progress, error, stop, info);
            }
        });
    };
    [[PHCachingImageManager defaultManager] requestPlayerItemForVideo:asset options:option resultHandler:^(AVPlayerItem *  playerItem, NSDictionary *  info) {
        if (completion) completion(playerItem, info);
    }];
    
    
}

+ (void)requestVideoURL_ForAsset:(PHAsset *)asset completion:(void (^)(NSURL *videoUrl, NSDictionary *info))completion
{
    [self requestVideoURL_ForAsset:asset progressHandler:^(double progress, NSError *error, BOOL *stop, NSDictionary *info) {
        
    } completion:completion];
}
+ (void)requestVideoURL_ForAsset:(PHAsset *)asset progressHandler:(void (^)(double progress, NSError *error, BOOL *stop, NSDictionary *info))progressHandler completion:(void (^)(NSURL *videoUrl, NSDictionary *info))completion
{
    PHVideoRequestOptions *option = [[PHVideoRequestOptions alloc] init];
    option.version = PHVideoRequestOptionsVersionOriginal;
    option.deliveryMode = PHVideoRequestOptionsDeliveryModeAutomatic;
    option.networkAccessAllowed = YES;
    option.progressHandler = ^(double progress, NSError *error, BOOL *stop, NSDictionary *info) {
        NSLog(@"progress:%f",progress);
        dispatch_async(dispatch_get_main_queue(), ^{
            if (progressHandler) {
                progressHandler(progress, error, stop, info);
            }
        });
    };
    //这种方式有点慢啊!!!(将视频资源的数据写入文件的导出会话)
    [[PHCachingImageManager defaultManager] requestExportSessionForVideo:asset options:option exportPreset:AVAssetExportPresetHighestQuality resultHandler:^(AVAssetExportSession *  exportSession, NSDictionary *  info) {
       
        AVURLAsset *asset = (AVURLAsset *)exportSession.asset;
        NSString *name = asset.URL.lastPathComponent;
        NSString *tmp = [XSFileManager tempFilePathWithPathComponent: name];
        [XSFileManager deletePath:tmp];
        NSURL *videoURL = [NSURL fileURLWithPath:tmp];
//        NSString *path = [XSFileManager tempVideoPath];
//        [XSFileManager deletePath:path];
//        NSURL *videoURL = [NSURL fileURLWithPath:path];
        //先存入沙盒中
        exportSession.outputFileType = AVFileTypeQuickTimeMovie;
        exportSession.outputURL = videoURL;
        [exportSession exportAsynchronouslyWithCompletionHandler:^{
            if (exportSession.status == AVAssetExportSessionStatusFailed) {
                NSLog(@"request failed:%@", exportSession.error);
            } else if(exportSession.status == AVAssetExportSessionStatusCompleted){
                NSLog(@"request completed videoURL:%@ -- %@",videoURL , info);
                dispatch_async(dispatch_get_main_queue(), ^{
                     completion(videoURL, info);
                });
               
            }
                    
        }];
        
    }];
    
    
}

+ (void)requestVideoPlayItem_ForAsset:(PHAsset *)asset progressHandler:(void (^)(double progress, NSError *error, BOOL *stop, NSDictionary *info))progressHandler completion:(void (^)(AVPlayerItem *  playerItem, NSDictionary *info))completion
{
    PHVideoRequestOptions *option = [[PHVideoRequestOptions alloc] init];
    option.networkAccessAllowed = YES;
    option.progressHandler = ^(double progress, NSError *error, BOOL *stop, NSDictionary *info) {
        NSLog(@"progress:%f",progress);
        dispatch_async(dispatch_get_main_queue(), ^{
            if (progressHandler) {
                progressHandler(progress, error, stop, info);
            }
        });
    };
     
    [[PHCachingImageManager defaultManager]requestPlayerItemForVideo:asset options:option resultHandler:^(AVPlayerItem *  playerItem, NSDictionary *  info) {
         NSLog(@"request completed videoURL:%@",info);
        dispatch_async(dispatch_get_main_queue(), ^{
            completion(playerItem, info);
        });
                    
    }];
 
    
}

+ (void)requestVideoAVAsset_ForAsset:(PHAsset *)asset progressHandler:(void (^)(double progress, NSError *error, BOOL *stop, NSDictionary *info))progressHandler completion:(void (^)(AVAsset *  asset, AVAudioMix *  audioMix, NSDictionary *info))completion
{
    PHVideoRequestOptions *option = [[PHVideoRequestOptions alloc] init];
    option.networkAccessAllowed = YES;
    option.progressHandler = ^(double progress, NSError *error, BOOL *stop, NSDictionary *info) {
        NSLog(@"progress:%f",progress);
        dispatch_async(dispatch_get_main_queue(), ^{
            if (progressHandler) {
                progressHandler(progress, error, stop, info);
            }
        });
    };
     
    [[PHCachingImageManager defaultManager]requestAVAssetForVideo:asset options:option resultHandler:^(AVAsset *  asset, AVAudioMix *  audioMix, NSDictionary *  info) {
        dispatch_async(dispatch_get_main_queue(), ^{
            completion(asset,audioMix,info);
        });
        
    }];
    
}


@end
